package org.lilred.nzbberry.http;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.io.HttpsConnection;

import net.rim.device.api.servicebook.ServiceBook;
import net.rim.device.api.servicebook.ServiceRecord;
import net.rim.device.api.system.CoverageInfo;
import net.rim.device.api.system.WLANInfo;

/**
 * HTTP Request Dispatcher class.  Provides methods for getting and posting. 
 */
public class HttpRequestDispatcher extends Thread {
    private String url;
    private String method; // GET or POST
    private RequestsHttp requester;
    private byte[] postData;

    /**
     * @param	url			fully qualified destination URL
     * @param	method		can be "GET" or "POST"
     * @param	requester	the object making the request, must implement the RequestsHttp interface
     * @param	postData	the byte array of data to post
     */
    public HttpRequestDispatcher(String url, String method, RequestsHttp requester, byte[] postData) {
        this.url = url;
        this.method = method;
        this.requester = requester;
        this.postData = postData;
    }
    
    /**
     * @param	url			fully qualified destination URL
     * @param	method		can be "GET" or "POST"
     * @param	requester	the object making the request, must implement the RequestsHttp interface
     */
    public HttpRequestDispatcher(String url, String method, RequestsHttp requester) {
        this.url = url;
        this.method = method;
        this.requester = requester;
    }

    private static ServiceRecord getWAP2ServiceRecord() {
        ServiceBook sb = ServiceBook.getSB();
        ServiceRecord[] records = sb.getRecords();

        for (int i = 0; i < records.length; i++) {
            String cid = records[i].getCid().toLowerCase();
            String uid = records[i].getUid().toLowerCase();
            if (cid.indexOf("wptcp") != -1 && uid.indexOf("wifi") == -1
                    && uid.indexOf("mms") == -1) {
                return records[i];
            }
        }

        return null;
    }


    public static String getConnectionParameters() {
        String connectionParameters = "";
        // JDE 4.3 is required to get WLANInfo
        if (WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED) {
            // Connected to a WiFi access point
            connectionParameters = ";interface=wifi";
        } else {
            int coverageStatus = CoverageInfo.getCoverageStatus();
            ServiceRecord record = getWAP2ServiceRecord();
            if (record != null
                    // In JDE 4.5 CoverageInfo changed the name of COVERAGE_CARRIER to COVERAGE_DIRECT
                    // The constant value for both is the same, '1', so you can use that to avoid any
                    // dependency on JDE 4.5
                    && (coverageStatus & 1) == 1) {
                // Have network coverage and a WAP 2.0 service book record
                connectionParameters = ";deviceside=true;ConnectionUID=" + record.getUid();
            } else if ((coverageStatus & CoverageInfo.COVERAGE_MDS) == CoverageInfo.COVERAGE_MDS) {
                // Have an MDS service book and network coverage
                connectionParameters = ";deviceside=false";
            } else if ((coverageStatus & 1) == 1) {
                // Have network coverage but no WAP 2.0 service book record
                connectionParameters = ";deviceside=true";
            }
        }
        return connectionParameters;
    }
    
    /**
     * Dispatches the thread.  Calls requester.requestSucceeded() or requester.requestFailed() when finished. 
     */
    public void run() {
        try {
        	String connectionParameters = getConnectionParameters();
            System.out.println("HTTP Request initiated.  Url: " + url);
            
            HttpConnection connection = (HttpConnection) Connector.open(url + connectionParameters);
            
            connection.setRequestMethod(method);
            if (method.equals("POST") && postData != null) {
                connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
                OutputStream requestOutput = connection.openOutputStream();
                requestOutput.write(postData);
                requestOutput.close();
            }
            int responseCode = connection.getResponseCode();
            System.out.println("Response Code: " + responseCode);
            if (connection instanceof HttpsConnection) {
                HttpsConnection secureConnection = (HttpsConnection) connection;
                String issuer = secureConnection.getSecurityInfo()
                        .getServerCertificate().getIssuer();
                System.out.println("Secure Connection! Certificate issued by: " + issuer);
            }

            String contentType = connection.getHeaderField("Content-type");
            System.out.println("Length: " + connection.getLength());

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            InputStream responseData = connection.openInputStream();
            byte[] buffer = new byte[10000];
            int bytesRead = responseData.read(buffer);
            while (bytesRead > 0) {
                baos.write(buffer, 0, bytesRead);
                bytesRead = responseData.read(buffer);
            }
            baos.close();
            connection.close();

            if (responseCode == HttpConnection.HTTP_OK)
            	requester.requestSucceeded(baos.toByteArray(), contentType);
            else requester.requestFailed(baos.toByteArray(), responseCode);
        } catch (IOException ex) {
            requester.requestFailed(ex.toString().getBytes(), 0);
        }
    }
}
